<template>
  <div class="player" v-show="playList.length">
    <transition name="normal">
      <div class="normal-player" v-show="isFullScreen">
        <div class="background">
          <img :src="currentSong.pic" />
        </div>
        <div class="top">
          <div class="back" @click="goBack">
            <i class="icon-back"></i>
          </div>
          <h1 class="title">{{ currentSong.name }}</h1>
          <h2 class="subtitle">{{ currentSong.singer }}</h2>
        </div>
        <div class="middle"
        @touchstart.prevent="onMiddleTouchStart"
        @touchmove.prevent="onMiddleTouchMove"
        @touchend.prevent="onMiddleTouchEnd">
          <div class="middle-l" :style="middleLStyle">
            <div class="cd-wrapper">
              <div class="cd" ref="cdRef">
                <img :src="currentSong.pic" class="image" :class="cdClass" ref="cdImageRef" />
              </div>
            </div>
            <div class="playing-lyric-wrapper">
              <div class="playing-lyric">{{ playingLyric }}</div>
            </div>
          </div>
          <Scroll class="middle-r" ref="lyricScrollRef" :style="middleRStyle">
            <div class="lyric-wrapper">
              <div v-if="currentLyric" ref="lyricListRef">
                <p class="text" :class="{ current: currentLineNum === index }" v-for="(line, index) in currentLyric.lines" :key="line.num">
                  {{ line.txt }}
                </p>
              </div>
              <div class="pure-music" v-show="pureMusicLyric">
                <p>{{ pureMusicLyric }}</p>
              </div>
            </div>
          </Scroll>
        </div>
        <div class="bottom">
          <div class="dot-wrapper">
            <span class="dot" :class="{ active: currentShow === 'cd' }"></span>
            <span class="dot" :class="{ active: currentShow === 'lyric' }"></span>
          </div>
          <div class="progress-wrapper">
            <span class="time time-l">{{ formatTime(currentTime) }}</span>
            <div class="progress-bar-wrapper">
              <progressBar :progress="progress" @progressChanged="onProgressChanged" @progressChanging="onProgressChanging" ref="barRef"></progressBar>
            </div>
            <span class="time time-r">{{ formatTime(currentSong.duration) }}</span>
          </div>
          <div class="operators">
            <div class="icon i-left">
              <i :class="modeIcon" @click="changeMode"></i>
            </div>
            <div class="icon i-left">
              <i class="icon-prev" @click="prev"></i>
            </div>
            <div class="icon i-center">
              <i :class="playIcon" @click="togglePlay"></i>
            </div>
            <div class="icon i-right">
              <i class="icon-next" @click="next"></i>
            </div>
            <div class="icon i-rigth">
              <i :class="getFavoriteIcon(currentSong)" @click="toggleFavorite(currentSong)"></i>
            </div>
          </div>
        </div>
      </div>
    </transition>

    <!-- 监听当前时间 -->
    <audio ref="audioRef" @timeupdate="updateTime" @ended="end" @canplay="ready"></audio>
    <MiniPlayer :progress="progress" :togglePlay="togglePlay"></MiniPlayer>
  </div>
</template>
<script>
import { useStore } from 'vuex'
import storage from 'good-storage'
import { computed, watch, ref, nextTick } from 'vue'
import { formatTime } from '@/js/utils'
import { PLAY_MODE, PLAY_KEY } from '@/js/constant'
import useMode from './use-mode'
import useFavorite from './use-favorite'
import useCd from './use-cd'
import useLyric from './use-lyric'
import usePlayHistory from './use-play-history'
import useInteractive from './use-interactive'
import progressBar from './progress-bar.vue'
import MiniPlayer from './mini-player.vue'
import Scroll from '@/components/base/scroll/scroll.vue'
export default {
  name: 'Player',
  components: {
    progressBar,
    Scroll,
    MiniPlayer
  },
  setup () {
    const store = useStore()
    const audioRef = ref(null)
    const barRef = ref(null)
    const songReady = ref(false)
    // 是否在拖动进度条
    let isDragging = false
    // 当前播放事件
    const currentTime = ref(0)
    const isFullScreen = computed(() => store.state.isFullScreen)
    const currentSong = computed(() => store.getters.currentSong)
    const playing = computed(() => store.state.isPlaying)
    // 暂停、播放按钮的icon切换
    const playIcon = computed(() => {
      return playing.value ? 'icon-pause' : 'icon-play'
    })
    const playMode = computed(() => store.state.playMode)
    const currentIndex = computed(() => store.state.currentIndex)
    const playList = computed(() => store.state.playList)
    const progress = computed(() => currentTime.value / currentSong.value.duration)
    // 监听currentSong的变化赋给audio赋值新的url
    watch(currentSong, (newSong) => {
      if (!newSong.id || !newSong.url) {
        return
      }
      const audioEl = audioRef.value
      currentTime.value = 0
      audioEl.src = newSong.url
      audioEl.play()
      store.commit('setPlayingState', true)
      savePlayHistory(currentSong.value)
      store.commit('setPlayHistory', storage.get(PLAY_KEY))
    })
    watch(playing, (newPlaying) => {
      if (!songReady.value) {
        return
      }
      const audioEl = audioRef.value
      newPlaying ? audioEl.play() : audioEl.pause()
      newPlaying ? playLyric() : stopLyric()
    })
    watch(isFullScreen, (newFullScreen) => {
      if (newFullScreen) {
        nextTick(() => {
          barRef.value.setOffset(progress.value)
        })
      }
    })
    // 前一首歌
    function prev () {
      const list = playList.value
      let index = currentIndex.value - 1
      if (index === -1) {
        index = list.length - 1
      }
      store.commit('setCurrentIndex', index)
      if (!playing.value) {
        store.commit('setPlayingState', true)
      }
    }
    // 暂停播放切换的实现
    function togglePlay () {
      store.commit('setPlayingState', !playing.value)
      const audioEl = audioRef.value
      playing.value ? audioEl.play() : audioEl.pause()
    }
    // 下一首歌
    function next () {
      const list = playList.value
      let index = currentIndex.value + 1
      if (index === list.length) {
        index = 0
      }
      store.commit('setCurrentIndex', index)
      if (!playing.value) {
        store.commit('setPlayingState', true)
      }
    }
    // 循环播放逻辑
    function loop () {
      const audioEl = audioRef.value
      audioEl.currentTime = 0
      audioEl.play()
      store.commit('setPlayingState', true)
    }
    function goBack () {
      store.commit('setFullScreen', false)
    }
    function updateTime (e) {
      if (!isDragging) {
        currentTime.value = e.target.currentTime
      }
    }
    function ready () {
      if (songReady.value) {
        return
      }
      songReady.value = true
      playLyric()
    }
    function end () {
      currentTime.value = 0
      if (playMode.value === PLAY_MODE.loop) {
        loop()
      } else {
        next()
      }
    }
    function onProgressChanging (progress) {
      isDragging = true
      currentTime.value = currentSong.value.duration * progress
      stopLyric()
      playLyric()
    }
    function onProgressChanged (progress) {
      isDragging = false
      currentTime.value = currentSong.value.duration * progress
      audioRef.value.currentTime = currentTime.value
      if (!playing.value) {
        store.commit('setPlayingState', true)
        const audioEl = audioRef.value
        audioEl.play()
      }
      playLyric()
    }

    // 切换播放模式hook
    const { modeIcon, changeMode } = useMode()
    // 收藏相关hook
    const { getFavoriteIcon, toggleFavorite } = useFavorite()
    // cd旋转hook
    const { cdRef, cdImageRef, cdClass } = useCd()
    // 获取歌词
    const { lyricScrollRef, lyricListRef, currentLyric, currentLineNum, playingLyric, pureMusicLyric, playLyric, stopLyric } = useLyric(songReady, currentTime)
    const { currentShow, middleLStyle, middleRStyle, onMiddleTouchStart, onMiddleTouchMove, onMiddleTouchEnd } = useInteractive()
    const { savePlayHistory } = usePlayHistory()

    return {
      audioRef,
      barRef,
      lyricScrollRef,
      lyricListRef,
      isFullScreen,
      currentSong,
      playIcon,
      togglePlay,
      goBack,
      prev,
      next,
      currentIndex,
      playList,
      modeIcon,
      changeMode,
      getFavoriteIcon,
      toggleFavorite,
      currentTime,
      progress,
      updateTime,
      formatTime,
      onProgressChanging,
      onProgressChanged,
      end,
      cdClass,
      cdRef,
      cdImageRef,
      currentLyric,
      currentLineNum,
      ready,
      playLyric,
      stopLyric,
      pureMusicLyric,
      playingLyric,
      middleLStyle,
      middleRStyle,
      onMiddleTouchStart,
      onMiddleTouchMove,
      onMiddleTouchEnd,
      currentShow,
      savePlayHistory
    }
  }
}
</script>
<style lang="scss" scoped>
.player {
  .normal-player {
    position: fixed;
    left: 0;
    right: 0;
    top: 0;
    bottom: 0;
    z-index: 150;
    background: $color-background;
    .background {
      position: absolute;
      left: 0;
      top: 0;
      width: 100%;
      height: 100%;
      z-index: -1;
      opacity: 0.6;
      filter: blur(0.852878rem);
      img {
        width: 100%;
        height: 100%;
      }
    }
    .top {
      position: relative;
      margin-bottom: 1.066098rem;
      margin-top: 0.852878rem;
      .back {
        position: absolute;
        top: 0;
        left: 0.255864rem;
        z-index: 50;
      }
      .icon-back {
        display: block;
        padding: 0.383795rem;
        margin-top: -0.426439rem;
        font-size: $font-size-large-x;
        color: $color-theme;
        transform: rotate(-90deg);
      }
      .title {
        width: 70%;
        margin: 0 auto;
        line-height: 1.705757rem;
        text-align: center;
        @include no-wrap();
        font-size: $font-size-large;
        color: $color-text;
      }
      .subtitle {
        line-height: 0.852878rem;
        text-align: center;
        font-size: $font-size-medium;
        color: $color-text;
      }
    }
    .middle {
      position: fixed;
      width: 100%;
      top: 3.411514rem;
      bottom: 7.249467rem;
      white-space: nowrap;
      font-size: 0;
      .middle-l {
        display: inline-block;
        vertical-align: top;
        position: relative;
        width: 100%;
        height: 0;
        padding-top: 80%;
        .cd-wrapper {
          position: absolute;
          left: 10%;
          top: 1.5rem;
          width: 80%;
          box-sizing: border-box;
          height: 100%;
          .cd {
            width: 100%;
            height: 100%;
            border-radius: 50%;
            img {
              position: absolute;
              left: 0;
              top: 0;
              width: 100%;
              height: 100%;
              box-sizing: border-box;
              border-radius: 50%;
              border: 0.426439rem solid rgba(255, 255, 255, 0.1);
            }
            .playing {
              animation: rotate 20s linear infinite;
            }
          }
        }
        .playing-lyric-wrapper {
          width: 80%;
          margin: 3.279318rem auto 0 auto;
          overflow: hidden;
          text-align: center;
          .playing-lyric {
            height: 0.852878rem;
            line-height: 0.852878rem;
            font-size: $font-size-medium;
            color: $color-text-l;
          }
        }
      }
      .middle-r {
        display: inline-block;
        vertical-align: top;
        width: 100%;
        height: 88%;
        overflow: hidden;
        .lyric-wrapper {
          width: 80%;
          margin: 0 auto;
          overflow: hidden;
          text-align: center;
          .text {
            line-height: 1.364606rem;
            color: $color-text-l;
            font-size: $font-size-medium;
            &.current {
              color: $color-theme;
            }
          }
          .pure-music {
            padding-top: 50%;
            line-height: 1.364606rem;
            color: $color-text-l;
            font-size: $font-size-medium;
          }
        }
      }
    }
    .bottom {
      position: absolute;
      bottom: 2.532196rem;
      width: 100%;
      .dot-wrapper {
        text-align: center;
        font-size: 0;
        .dot {
          display: inline-block;
          vertical-align: middle;
          margin: 0 .170576rem;
          width: .341151rem;
          height: .341151rem;
          border-radius: 50%;
          background: $color-text-l;
          &.active {
            width: .852878rem;
            border-radius: .21322rem;
            background: $color-text-ll;
          }
        }
      }
      .operators {
        display: flex;
        align-items: center;
        .icon {
          flex: 1;
          color: $color-theme;
          &.disable {
            color: $color-theme-d;
          }
          i {
            font-size: 1.279318rem;
          }
        }
        .i-left {
          text-align: right;
        }
        .i-center {
          padding: 0 0.852878rem;
          text-align: center;
          i {
            font-size: 1.705757rem;
          }
        }
        .i-right {
          text-align: left;
        }
        .icon-favorite {
          color: $color-sub-theme;
        }
      }
      .progress-wrapper {
        display: flex;
        align-items: center;
        width: 80%;
        margin: 0.8rem auto;
        padding: 0.426439rem 0;
        .time {
          color: $color-text;
          font-size: $font-size-small;
          flex: 0 0 1.705757rem;
          line-height: 1.279318rem;
          width: 1.705757rem;
          &.time-l {
            text-align: left;
          }
          &.time-r {
            text-align: right;
          }
        }
        .progress-bar-wrapper {
          flex: 1;
        }
      }
    }
     &.normal-enter-active, &.normal-leave-active {
        transition: all .6s;
        .top, .bottom {
          transition: all .6s linear;
        }
      }
      &.normal-enter-from, &.normal-leave-to {
        opacity: 0;
        .top {
          transform: translate3d(0, -100px, 0);
        }
        .bottom {
          transform: translate3d(0, 100px, 0)
        }
      }
  }
}
</style>
